package com.imyuanma.qingyun.common.config.security;

import com.imyuanma.qingyun.common.util.JsonUtil;
import com.imyuanma.qingyun.common.util.StringUtil;
import com.imyuanma.qingyun.common.util.WebUtil;
import com.imyuanma.qingyun.interfaces.ums.model.SsoVerifyDTO;
import com.imyuanma.qingyun.interfaces.ums.service.IUmsPermissionsOutService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 上下文资源库
 *
 * @author wangjy
 * @date 2022/07/16 10:26:15
 */
@Component
public class DefaultSecurityContextRepository implements SecurityContextRepository {
    private static final Logger logger = LoggerFactory.getLogger(DefaultSecurityContextRepository.class);

    /**
     * 权限服务
     */
    @Autowired
    private IUmsPermissionsOutService permissionsOutService;

    /**
     * 加载上下文
     *
     * @param requestResponseHolder
     * @return
     */
    @Override
    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
        logger.info("[上下文资源库-加载上下文] 获取当前请求的用户上下文");
        HttpServletRequest request = requestResponseHolder.getRequest();
        String tokenForCookie = WebUtil.getCookieValue(request, SecurityConstants.TOKEN_KEY);
        String tokenForHeader = request.getHeader(SecurityConstants.TOKEN_KEY);
        String tokenForParam = request.getParameter(SecurityConstants.TOKEN_KEY);
        logger.info("[上下文资源库-加载上下文] cookie-token={},header-token={},parameter-token={}", tokenForCookie, tokenForHeader, tokenForParam);
        String token = StringUtil.getFirstValid(tokenForCookie, tokenForHeader, tokenForParam);
        if (StringUtil.isNotBlank(token)) {
            SsoVerifyDTO ssoVerifyDTO = permissionsOutService.verifySSO(token);
            if (ssoVerifyDTO != null && ssoVerifyDTO.isSuccess()) {
                SecurityContext context = new SecurityContextImpl();
                SsoAuthenticationToken ssoAuthenticationToken = new SsoAuthenticationToken(ssoVerifyDTO);
                ssoAuthenticationToken.setAuthenticated(true);
                context.setAuthentication(ssoAuthenticationToken);
                return context;
            } else {
                logger.info("[上下文资源库-加载上下文] 根据token={}获取sso信息返回空或失败={}", token, JsonUtil.toJson(ssoVerifyDTO));
            }
        } else {
            logger.info("[上下文资源库-加载上下文] 获取token为空");
        }
        return SecurityContextHolder.createEmptyContext();
    }

    /**
     * 保存上下文
     *
     * @param context
     * @param request
     * @param response
     */
    @Override
    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
        logger.info("[上下文资源库-保存上下文] 当前请求的上下文信息={}", JsonUtil.toJson(context));
//        if (context != null && context.getAuthentication() != null) {
//            Authentication authentication = context.getAuthentication();
//            if (authentication instanceof UsernamePasswordAuthenticationToken
//                    && authentication.isAuthenticated()
//                    && authentication.getPrincipal() instanceof DefaultUserDetails
//            ) {
//                DefaultUserDetails userDetails = (DefaultUserDetails) authentication.getPrincipal();
//                logger.info("[上下文资源库-保存上下文] 当前认证属于账号密码认证对象(登录场景),写入凭证token={}到响应头", userDetails.getToken());
//                Cookie cookie = new Cookie(SecurityConstants.TOKEN_KEY, userDetails.getToken());
//                cookie.setPath("/");
//                cookie.setDomain("localhost");
//                response.addCookie(cookie);
//            }
//        }
    }

    /**
     * Allows the repository to be queried as to whether it contains a security context
     * for the current request.
     *
     * @param request the current request
     * @return true if a context is found for the request, false otherwise
     */
    @Override
    public boolean containsContext(HttpServletRequest request) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        boolean res = securityContext != null && securityContext.getAuthentication() instanceof SsoAuthenticationToken;
        logger.info("[上下文资源库-是否存在上下文] 判断上下文是否SsoAuthenticationToken实例,结果={},上下文={}", res, JsonUtil.toJson(securityContext));
        return res;
    }
}
